// 1067. [多源BFS]最小距离和 https://oj.rnd.huawei.com/problems/1067/details
// 力扣：腐烂的橘子
//计算每个零售店走到最近仓库的距离，并输出这些最小距离的和。商店
//矩阵元素的值仅为三种：0，表示仓库； -1，表示障碍； 1，表示零售店。
//注：障碍无法通过，其它可以通过。
// m*n 的数组
// 输入 3 3
// 1 -1 0
// 0 1 1
// 1 -1 1
// 输出 6
// 输入 2 3
// 0 -1 1
// 1 -1 1
// 输出1

#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#include <vector>
using namespace std;

class Solution {
 public:
  // 待实现函数，在此函数中填入答题代码
  int NearestWareHouse1(const vector<vector<int>>& grid) {
    vector<pair<int, int>> dirs{{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
    queue<tuple<int, int, int>> queBlock;
    bool hasStore = false;
    size_t nW = grid.size();
    size_t nH = grid.front().size();

    vector<vector<bool>> isVisited(nW, vector<bool>(nH, false));
    vector<vector<int>> dist(nW, vector<int>(nH, 0));
    for (size_t i = 0; i < nW; ++i) {
      for (size_t j = 0; j < nH; ++j) {
        if (grid[i][j] == 1) {
          hasStore = true;
        }
        if (grid[i][j] == 0) {
          queBlock.push(make_tuple(i, j, 0));
          isVisited[i][j] = true;
        }
      }
    }
    if (!hasStore || queBlock.empty()) {
      return 0;
    }
    while (!queBlock.empty()) {
      auto [i, j, dis] = queBlock.front();
      queBlock.pop();
      for (auto [dx, dy] : dirs) {
        int x = i + dx, y = j + dy;
        if (x < 0 || x >= nW || y < 0 || y >= nH) {
          continue;
        }
        if (isVisited[x][y] || grid[x][y] == -1) {
          continue;
        }
        if (grid[x][y] == 1) {
          dist[x][y] = dis + 1;
        }
        isVisited[x][y] = true;
        queBlock.push({x, y, dis + 1});
      }
    }
    int ret = 0;
    for (size_t i = 0; i < nW; ++i) {
      for (size_t j = 0; j < nH; ++j) {
        if (grid[i][j] == 1) {
          // printf("%d,%d=%d\n", i,j,dist[i][j]);
          ret += dist[i][j];
        }
      }
    }
    return ret;
  }
};
// 以下为考题输入输出框架，此部分代码不建议改动
template <typename T>
inline std::vector<T> ReadVector(int size) {
  std::vector<T> objects(size);
  for (int i = 0; i < size; ++i) {
    std::cin >> objects[i];
  }
  return objects;
}
int main() {
  int m = 0;
  int n = 0;
  cin >> m >> n;
  vector<vector<int>> grid;

  while (m > 0) {
    auto row = ReadVector<int>(n);
    if (!row.empty()) {
      grid.push_back(row);
      m--;
    }
  }

  Solution solu;
  int got = solu.NearestWareHouse1(grid);
  cout << got << endl;

  return 0;
}
